/*
 * Copyright (c) 2018, dreamkaylee@foxmail.com All Rights Reserved.
 */

package com.common.shiro.util;

import java.io.Serializable;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.common.manager.ClientManager;
import com.common.shiro.bean.UserModel;

/**
 * shiro session管理工具
 * 
 * @author limk
 * @date 2018年2月12日 下午9:07:32
 * @version 1.2
 */
public class ShiroCacheUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(ShiroCacheUtil.class);

	private static CacheManager cacheManager;
	
	/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~session相关~~~~~~~~~~~~~~~~~~~~~~ */

	/**
	 * 从cache拿当前user
	 * 
	 * @return
	 */
	public static UserModel getCurrentUser() {

		Subject subject = getSubject();
		PrincipalCollection collection = subject.getPrincipals();
		if (null != collection && !collection.isEmpty()) {
			return (UserModel) collection.iterator().next();
		}
		return null;
	}

	/**
	 * 获得当前用户名
	 * 
	 * @return
	 */
	public static String getCurrentUsername() {
		UserModel user = getCurrentUser();
		return null != user ? user.getUserName() : null;
	}

	/**
	 * 获取当前用户的session
	 * 
	 * @return
	 */
	public static Session getSession() {
		return SecurityUtils.getSubject().getSession();
	}

	/**
	 * 获取当前用户的session的ID
	 * 
	 * @return
	 */
	public static String getSessionId() {
		Session session = getSession();
		if (null == session) {
			return null;
		}
		return getSession().getId().toString();
	}

	/**
	 * 此方法会会遍历所有的session
	 * 
	 * @param username
	 * @return
	 */
	public static Session getSessionByUsername(String username) {
		Cache<Object, Object> sessionCache = getSessionCache();
		String sessionid = ClientManager.getInstance().getSessionId(username);
		return (Session) sessionCache.get(sessionid);
	}

	/**
	 * 踢除用户,此方法会会遍历所有的session
	 * 
	 * @param username
	 */
	public static boolean kickOutUser(String username) {
		LOGGER.info("强制下线！");
		Session session = getSessionByUsername(username);
		if (null != session
				&& !StringUtils.equals(String.valueOf(session.getId()), getSessionId())) {
			clearAuthenticationInfo(session.getId());
			return true;
		}
		return false;
	}
	
	/**
	 * 踢除用户,此方法会会遍历所有的session
	 * 
	 * @param sessionId
	 */
	public static void kickOutUserBySessionId(String sessionId) {
		LOGGER.info("强制下线！");
		String username = ClientManager.getInstance().getClient(sessionId).getUserName();
		kickOutUser(username);
	}

	/**
	 * 判断当前用户是否已通过认证
	 * 
	 * @return
	 */
	public static boolean hasAuthenticated() {
		return getSubject().isAuthenticated();
	}

	private static Subject getSubject() {
		return SecurityUtils.getSubject();
	}

	/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~缓存相关~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

	/**
	 * 获取session缓存
	 * 
	 * @return
	 */
	public static Cache<Object, Object> getSessionCache() {
		return cacheManager.getCache("activeSessionCache");
	}

	/**
	 * 获取用户认证信息缓存
	 * 
	 * @return
	 */
	public static Cache<Object, Object> getAuthenticationCache() {
		return cacheManager.getCache("authenticationCache");
	}

	/**
	 * 清除用户的授权信息
	 * 
	 * @param username
	 */
	public static void clearAuthorizationInfo(String username) {
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("clear the " + username + " authorizationInfo");
		}
		Cache<Object, Object> cache = cacheManager.getCache("authorizationCache");
		cache.remove(username);
	}

	/**
	 * 清除当前用户的授权信息
	 */
	public static void clearAuthorizationInfo() {
		if (hasAuthenticated()) {
			clearAuthorizationInfo(getCurrentUsername());
		}
	}

	/**
	 * 清除session(认证信息)
	 * 
	 * @param JSESSIONID
	 */
	public static void clearAuthenticationInfo(Serializable jsessionid) {
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("clear the session " + jsessionid);
		}
		Cache<Object, Object> cache = cacheManager.getCache("activeSessionCache");
		cache.remove(jsessionid);
	}

	/**
	 * 获取缓存管理
	 * 
	 * @return
	 */
	public static CacheManager getCacheManager() {
		return cacheManager;
	}

	public void setCacheManager(CacheManager cacheManager) {
		ShiroCacheUtil.cacheManager = cacheManager;
	}

}
